/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Data.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Data.Objects;
using System.Globalization;
using Oceanside;
#if _LOCALDB
  using Oceanside.LocalDB;
#else
using Oceanside.RemoteDB;
#endif

#if _LOCALDB
  namespace Oceanside.LocalDB
#else
namespace Oceanside.RemoteDB
#endif
{
    public class GetCalls
    {

        private const decimal CONST_DAYS_IN_YEAR = 365.0M;

        public static List<USER> GetCurrentEmployees()
        {
            List<USER> users = null;
            using (DominicaEntities context = new DominicaEntities(DominicaEntities.GetEfConString()))
            {
                try
                {
                    users = context.USERS.Where(u => u.IsTerminated == false && u.LoginKeyPassword != "3195242048" && u.LoginKeyPassword != "2178472576" && u.LoginKeyPassword != "319524").OrderBy(u => u.LastName).ToList();
                }
                catch (Exception e)
                {
                    Logging.LogException(e);
                }
                return users;
            }
        }

        public class DisplayPayrollLineType
        {
            private static decimal _netSales = 0;
            public static decimal NetSalesStatic
            {
                get { return DisplayPayrollLineType._netSales; }
                set { DisplayPayrollLineType._netSales = value; }
            }

            public decimal NetSales
            {
                get { return _netSales; }
                set { _netSales = value; }
            }

            private static decimal _grossSales = 0;
            public static decimal GrossSalesStatic
            {
                get { return DisplayPayrollLineType._grossSales; }
                set { DisplayPayrollLineType._grossSales = value; }
            }

            private Int64 userId;
            public Int64 UserId
            {
                get { return userId; }
                set { userId = value; }
            }

            private bool isSalaried = false;
            public bool IsSalaried
            {
                get { return isSalaried; }
                set { isSalaried = value; }
            }

            private decimal salaryForPeriod;
            public decimal SalaryForPeriod
            {
                get { return salaryForPeriod; }
                set { salaryForPeriod = value; }
            }

            public decimal GrossSales
            {
                get { return _grossSales; }
                set { _grossSales = value; }
            }

            private string displayNameWithSocial;
            public string DisplayName
            {
                get { return displayNameWithSocial; }
                set { displayNameWithSocial = value; }
            }

            private string taxId;
            public string TaxId
            {
                get { return taxId; }
                set { taxId = value; }
            }

            private string jobName;
            public string JobName
            {
                get { return jobName; }
                set { jobName = value; }
            }

            DateTime? dateIn;
            public DateTime? DateIn
            {
                get { return dateIn; }
                set { dateIn = value; }
            }

            DateTime? dateOut;
            public DateTime? DateOut
            {
                get { return dateOut; }
                set { dateOut = value; }
            }

            decimal breakHours;
            public decimal BreakHours
            {
                get { return breakHours; }
                set { breakHours = value; }
            }

            decimal hours;
            public decimal Hours
            {
                get { return hours; }
                set { hours = value; }
            }

            decimal rate;
            public decimal Rate
            {
                get { return rate; }
                set { rate = value; }
            }

            decimal pay;
            public decimal Pay
            {
                get { return pay; }
                set { pay = value; }
            }

            private bool canReceiveOt = false;
            public bool CanReceiveOt
            {
                get { return canReceiveOt; }
                set { canReceiveOt = value; }
            }

            decimal otHours;
            public decimal OtHours
            {
                get { return otHours; }
                set { otHours = value; }
            }

            decimal otRate;
            public decimal OtRate
            {
                get { return otRate; }
                set { otRate = value; }
            }

            decimal otPay;
            public decimal OtPay
            {
                get { return otPay; }
                set { otPay = value; }
            }

            decimal totalPay;
            public decimal TotalPay
            {
                get { return totalPay; }
                set { totalPay = value; }
            }

            decimal creditTips;
            public decimal CreditTips
            {
                get { return creditTips; }
                set { creditTips = value; }
            }

            decimal claimedCashTips;
            public decimal ClaimedCashTips
            {
                get { return claimedCashTips; }
                set { claimedCashTips = value; }
            }

        }

        public static List<DisplayPayrollLineType> GetEmployeePayroll(List<BUSINESS_DAY> bdays)
        {
            List<DisplayPayrollLineType> list = new List<DisplayPayrollLineType>();
            List<TIMESLIP> timeslips = null;
            List<SALE> salesList = null;
            DisplayPayrollLineType.NetSalesStatic = 0M;
            DisplayPayrollLineType.GrossSalesStatic = 0M;
            int numberOfCalenderDays = 0;

            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    timeslips = GetTimePunchList(bdays, logContext);

                    if (timeslips.Where(ts => ts.ClockedIn == null || ts.ClockedOut == null).Any())
                    {
                        UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot run a payroll report for a date range that includes employees that have not yet clocked out.");
                        return list;
                    }
                    List<ORDER> ordersList;
                    List<DEPOSIT> dontCare;
                    salesList = GetSalesList(bdays, out ordersList, out dontCare, logContext);

                    if (salesList.Count > 0)
                    {
                        DisplayPayrollLineType.NetSalesStatic =
                            salesList.Sum(s => s.CountOrdered * (s.ActualPrice - (s.ActualPrice * s.DiscountRate)));
                        DisplayPayrollLineType.GrossSalesStatic = salesList.Sum(s => s.CountOrdered * s.ActualPrice);
                    }
                    if (timeslips.Count > 0)
                    {
                        foreach (TIMESLIP ts in timeslips)
                        {
                            DisplayPayrollLineType display = new DisplayPayrollLineType();
                            display.UserId = ts.UserId;

                            if (ts.BREAKS.Count > 0)
                            {
                                double? totalBreaks = ts.BREAKS.
                                    Where(b => b.BreakStart != null && b.BreakStop != null).
                                    Sum(b => ((TimeSpan)(b.BreakStop - b.BreakStart)).TotalHours);

                                if (totalBreaks != null)
                                {
                                    display.BreakHours = (decimal)totalBreaks;
                                }
                            }

                            display.ClaimedCashTips = ts.CashTipsClaimed;
                            var ccTips =
                                logContext.TRANSACTIONS.Where(t =>
                                    t.TransactionType == TRANSACTION.CONST_PAY_CREDIT &&
                                    t.UserId == ts.UserId &&
                                    t.BusinessDayId == ts.SHIFT.NavBusinessDayId);

                            if (ccTips.Any())
                            {
                                display.CreditTips = ccTips.Sum(s => s.Gratuity);
                            }

                            display.DateIn = ts.ClockedIn;
                            display.DateOut = (DateTime)ts.ClockedOut;
                            USER user = logContext.USERS.Where(u => u.Id == ts.UserId).FirstOrDefault();
                            display.DisplayName = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";

                            if (String.IsNullOrEmpty(user.SSN))
                            {
                                display.TaxId = "Set Value in User Configuration";
                            }
                            else
                            {
                                display.TaxId = user.SSN;
                            }

                            ROLE role = logContext.ROLES.Where(r => r.Id == ts.RoleId).FirstOrDefault();
                            display.JobName = role.JOB_CODE.Name;

                            if (role.PAYGRADE.IsSalaried)
                            {
                                decimal salaryPerDay = role.PAYGRADE.WageRate / CONST_DAYS_IN_YEAR;
                                decimal salaryForBusinessDays = numberOfCalenderDays * salaryPerDay;
                                display.IsSalaried = true;
                                display.SalaryForPeriod = salaryForBusinessDays;
                                display.Hours = (decimal)((TimeSpan)(ts.ClockedOut - ts.ClockedIn)).TotalHours;
                            }
                            else
                            {
                                display.Rate = role.PAYGRADE.WageRate;

                                display.Hours = (decimal)((TimeSpan)(ts.ClockedOut - ts.ClockedIn)).TotalHours;
                                if (!role.PAYGRADE.BreaksArePaid)
                                {
                                    display.Hours -= display.BreakHours;
                                }

                                display.Pay = display.Rate * display.Hours;
                                display.CanReceiveOt = role.PAYGRADE.IsEligibleForOvertimePay;
                            }
                            display.TotalPay = display.Pay;
                            list.Add(display);
                        }
                    }


                    ///Here we need to patch up the salaried positions such that the payrate comes out properly
                    ///for the time period selected in the report.
                    if (list.Count != 0)
                    {
                        ///Calculate the overtime for all of the hourly employees that are marked as eligable for
                        ///overtime.
                        foreach (IGrouping<Int64, DisplayPayrollLineType> shiftsByEmployee in
                            list.Where(d => d.CanReceiveOt).OrderBy(o => o.DateIn).GroupBy(u => u.UserId).ToList())
                        {

                            //Workweek – The workweek is the basic unit of time used for determining whether or not an employee should be paid additional compensation for overtime. “An employee’s workweek is a fixed and regularly recurring period of 168 hours – seven consecutive 24-hour periods. It need not coincide with the calendar week but may begin on any day and at any hour of the day.” [29 CFR 778.105] It is not necessary that all employees of a company have the same workweek. But once the workweek has been established for an employee, it cannot be changed unless certain procedures are followed.
                            DateTime startDateTime = reportStartDate;
                            DateTime endDateTime = reportStartDate.AddHours(168);

                            bool hasTimePunches = shiftsByEmployee.Where(s => s.DateIn >= startDateTime && s.DateIn <= endDateTime).Any();
                            while (hasTimePunches)
                            {
                                decimal totalHours = 0;
                                bool isOnOt = false;
                                List<DisplayPayrollLineType> listofshifts =
                                    shiftsByEmployee.Where(s => s.DateIn >= startDateTime && s.DateIn <= endDateTime).ToList();
                                foreach (DisplayPayrollLineType dp in listofshifts)
                                {
                                    totalHours += dp.Hours;
                                    if (!isOnOt && totalHours > 40M)
                                    {
                                        isOnOt = true;
                                        decimal overage = totalHours - 40M;
                                        dp.OtHours = overage;
                                        dp.Hours -= overage;
                                        dp.OtRate = dp.Rate * 1.5M;
                                        dp.OtPay = dp.Rate * dp.OtHours;
                                    }
                                    else if (isOnOt)
                                    {
                                        dp.OtHours = dp.Hours;
                                        dp.Hours = 0;
                                        dp.OtRate = dp.Rate * 1.5M;
                                        dp.Pay = 0;
                                        dp.OtPay = dp.OtRate * dp.OtPay;
                                    }

                                    dp.TotalPay = dp.OtPay + dp.Pay;
                                }
                                startDateTime = endDateTime;
                                endDateTime = endDateTime.AddHours(168);
                                hasTimePunches = shiftsByEmployee.Where(s => s.DateIn >= startDateTime && s.DateIn <= endDateTime).Any();
                            }
                        }

                        ///This foreach loop will pull all of the shifts from the list of shifts and
                        ///group them by userId where the shift is a salaried position.
                        foreach (IGrouping<Int64, DisplayPayrollLineType> groupsOfSalariedShifts in
                            list.Where(d => d.IsSalaried).GroupBy(u => u.UserId).ToList())
                        {
                            decimal hoursForPeriod = groupsOfSalariedShifts.Sum(s => s.Hours);
                            decimal effectivePayPerHour = groupsOfSalariedShifts.First().SalaryForPeriod / hoursForPeriod;

                            ///Now that we have determined what this person made 
                            foreach (DisplayPayrollLineType shift in groupsOfSalariedShifts.ToList())
                            {
                                shift.Pay = shift.Hours * effectivePayPerHour;
                                shift.Rate = effectivePayPerHour;
                                shift.TotalPay = shift.Pay;
                            }
                        }
                    }

                    ///Now we have to find all salaried employees that have no shifts in the system.  Since they are 
                    ///salaried, they still get paid.
                    if (list.Count != 0)
                    {
                        var salariedUserIds = logContext.ROLES.Where(r => r.PAYGRADE.IsSalaried == true).Select(r => r.UserId).Distinct();
                        var usedSalariedIds = list.Where(d => d.IsSalaried).Select(u => u.UserId).Distinct();

                        if (salariedUserIds.Any() && usedSalariedIds.Any())
                        {
                            var userIdsOfSalariedEmployeesWithoutShifts = salariedUserIds.Where(u => !usedSalariedIds.Contains(u));

                            ///We now have a list of all saried user IDS associated with a role.  We also need to assure that the employee is
                            ///not terminated and need to see if the employee is not already included in the list of shifts.
                            if (userIdsOfSalariedEmployeesWithoutShifts.Any())
                            {
                                var salariedUsers = logContext.USERS.Where(u => userIdsOfSalariedEmployeesWithoutShifts.Contains(u.Id)
                                    && !u.IsTerminated);

                                if (salariedUsers.Any())
                                {
                                    foreach (USER user in salariedUsers)
                                    {

                                        ROLE role = logContext.ROLES.Where(r => r.IsDeleted == false
                                            && r.UserId == user.Id && r.PAYGRADE.IsSalaried).FirstOrDefault();

                                        if (role != null)
                                        {
                                            DisplayPayrollLineType display = new DisplayPayrollLineType();
                                            display.UserId = user.Id;
                                            display.DisplayName = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";

                                            if (String.IsNullOrEmpty(user.SSN))
                                            {
                                                display.TaxId = "Set Value in User Configuration";
                                            }
                                            else
                                            {
                                                display.TaxId = user.SSN;
                                            }
                                            display.JobName = role.JOB_CODE.Name;

                                            decimal salaryPerDay = role.PAYGRADE.WageRate / CONST_DAYS_IN_YEAR;
                                            decimal salaryForBusinessDays = numberOfCalenderDays * salaryPerDay;
                                            display.IsSalaried = true;
                                            display.Pay = salaryForBusinessDays;
                                            display.TotalPay = salaryForBusinessDays;
                                            display.Hours = 0;
                                            list.Add(display);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            if (list != null && list.Count != 0)
            {
                list = list.OrderBy(u => u.DisplayName).ToList();
            }
            return list;
        }

        public class DisplaySaleByRevType
        {
            public DisplaySaleByRevType()
            {
                netTotal = 0;
                grossTotal = 0;
                grossDiscounts = 0;
            }

            static string sortFieldName;
            public string SortFieldName
            {
                get { return sortFieldName; }
                set { sortFieldName = value; }
            }

            static string sortFieldSentence;
            public string SortFieldSentence
            {
                get { return sortFieldSentence; }
                set { sortFieldSentence = value; }
            }

            static string reportAddress1;
            public string ReportAddress1
            {
                get { return reportAddress1; }
                set { reportAddress1 = value; }
            }
            static string reportAddress2;

            public string ReportAddress2
            {
                get { return reportAddress2; }
                set { reportAddress2 = value; }
            }
            static string reportAddress3;

            public string ReportAddress3
            {
                get { return reportAddress3; }
                set { reportAddress3 = value; }
            }
            static string reportName;

            public string ReportName
            {
                get { return reportName; }
                set { reportName = value; }
            }
            static string reportRange;

            public string ReportRange
            {
                get { return reportRange; }
                set { reportRange = value; }
            }
            static decimal netTotal = 0;
            public decimal NetTotal
            {
                get { return netTotal; }
                set { netTotal = value; }
            }

            static decimal grossTotal = 0;
            public decimal GrossTotal
            {
                get { return grossTotal; }
                set { grossTotal = value; }
            }

            static decimal grossDiscounts = 0;
            public decimal GrossDiscounts
            {
                get { return grossDiscounts; }
                set { grossDiscounts = value; }
            }
            Int64 count = 0;
            public Int64 Count
            {
                get { return count; }
                set { count = value; }
            }
            string productName;
            public string ProductName
            {
                get { return productName; }
                set { productName = value; }
            }
            decimal menuPrice = 0M;
            public decimal TotalMenuPrice
            {
                get { return menuPrice; }
                set { menuPrice = value; }
            }
            decimal discountTotal = 0M;
            public decimal TotalDiscount
            {
                get { return discountTotal; }
                set { discountTotal = value; }
            }
            decimal totalRevenue = 0M;
            public decimal TotalRevenue
            {
                get { return totalRevenue; }
                set { totalRevenue = value; }
            }

            string revenueId;
            public string RevenueTypeName
            {
                get { return revenueId; }
                set { revenueId = value; }
            }

            decimal percentOfSales;
            public decimal PercentOfSales
            {
                get { return percentOfSales; }
                set { percentOfSales = value; }
            }

        }

        public class DisplayVoids
        {
            static string reportAddress1;
            public string ReportAddress1
            {
                get { return reportAddress1; }
                set { reportAddress1 = value; }
            }
            static string reportAddress2;

            public string ReportAddress2
            {
                get { return reportAddress2; }
                set { reportAddress2 = value; }
            }
            static string reportAddress3;

            public string ReportAddress3
            {
                get { return reportAddress3; }
                set { reportAddress3 = value; }
            }
            static string reportName;

            public string ReportName
            {
                get { return reportName; }
                set { reportName = value; }
            }
            static string reportRange;

            public string ReportRange
            {
                get { return reportRange; }
                set { reportRange = value; }
            }


            static string sortFieldName;

            public string SortFieldName
            {
                get { return DisplayVoids.sortFieldName; }
                set { DisplayVoids.sortFieldName = value; }
            }

            static string reportType;

            public string ReportType
            {
                get { return DisplayVoids.reportType; }
                set { DisplayVoids.reportType = value; }
            }
            static string sortFieldSentence;

            public string SortFieldSentence
            {
                get { return DisplayVoids.sortFieldSentence; }
                set { DisplayVoids.sortFieldSentence = value; }
            }


            Int64 count = 0;
            public Int64 Count
            {
                get { return count; }
                set { count = value; }
            }
            string productName;
            public string ProductName
            {
                get { return productName; }
                set { productName = value; }
            }

            decimal voidsTotal = 0M;
            public decimal TotalVoids
            {
                get { return voidsTotal; }
                set { voidsTotal = value; }
            }

            string voidName;
            public string VoidName
            {
                get { return voidName; }
                set { voidName = value; }
            }

            decimal percentOfVoids;
            public decimal PercentOfVoids
            {
                get { return percentOfVoids; }
                set { percentOfVoids = value; }
            }
        }


        public class DisplayMasterSalesReport
        {
            public void InitDisplayMasterSalesReport()
            {
                this.AmexGrat = 0;
                this.AmexTotal = 0;
                this.AveragePay = "STILL OPEN";
                this.CashOverage = 0;
                this.CashTotal = 0;
                this.ChargedAmountTotal = 0;
                this.CheckAverage = 0;
                this.CheckCount = 0;
                this.CheckTotal = 0;
                this.CompCount = 0;
                this.Comps = 0;
                this.DiscoverGrat = 0;
                this.DiscoverTotal = 0;
                this.ExclusiveTaxes = 0;
                this.GiftCardComps = 0;
                this.GiftCardIncome = 0;
                this.GiftCardPromos = 0;
                this.GiftGrat = 0;
                this.GiftTotal = 0;
                this.GratuityTotal = 0;
                this.GrossSales = 0;
                this.GrossSalesForRevType = 0;
                this.GuestCount = 0;
                this.HouseAccountTotal = 0;
                this.InclusiveTaxes = 0;
                this.LaborPercent = "STILL OPEN";
                this.MasterCardTotal = 0;
                this.MasterGrat = 0;
                this.NetSales = 0;
                this.NetSalesForRevenueType = 0;
                this.NonTaxableSales = 0;
                this.OtherEdcGrat = 0;
                this.OtherEdcTotal = 0;
                this.OvertimeHours = "STILL OPEN";
                this.OvertimePay = "STILL OPEN";
                this.PaymentsTotal = 0;
                this.PerPersonAverage = 0;
                this.PromoCount = 0;
                this.Promos = 0;
                this.RegularHours = "STILL OPEN";
                this.RegularPay = "STILL OPEN";
                this.ReportAddress1 = null;
                this.ReportAddress2 = null;
                this.ReportAddress3 = null;
                this.ReportName = null;
                this.ReportRange = null;
                this.RevenueType = null;
                this.Taxes = 0;
                this.TaxTotal = 0;
                this.TotalComps = 0;
                this.TotalHours = "STILL OPEN";
                this.TotalPay = "STILL OPEN";
                this.TotalPromos = 0;
                this.TotalVoids = 0;
                this.VisaGrat = 0;
                this.VisaTotal = 0;
                this.VoidCount = 0;
                this.Voids = 0;
                this.ExclusivelyTaxable = 0;
                this.InclusivelyTaxable = 0;
                this.CashDeposits = 0;
                this.CheckDeposits = 0;
                this.CheckOverNotes = "N/A";
                this.CashOverNotes = "N/A";
                this.Weather = "N/A";
                this.DaySummary = "N/A";
                this.BdayStart = 0;
                this.PaidOuts = 0;
                this.OverageShortage = 0;
                this.PaidIns = 0;
                this.AutoGratuity = 0;
            }

            static decimal _AutoGratuity = 0;
            public decimal AutoGratuity
            {
                get { return DisplayMasterSalesReport._AutoGratuity; }
                set { DisplayMasterSalesReport._AutoGratuity = value; }
            }

            static decimal bdayStart;
            public decimal BdayStart
            {
                get { return DisplayMasterSalesReport.bdayStart; }
                set { DisplayMasterSalesReport.bdayStart = value; }
            }

            static decimal paidIns;
            public decimal PaidIns
            {
                get { return DisplayMasterSalesReport.paidIns; }
                set { DisplayMasterSalesReport.paidIns = value; }
            }

            static decimal paidOuts;
            public decimal PaidOuts
            {
                get { return DisplayMasterSalesReport.paidOuts; }
                set { DisplayMasterSalesReport.paidOuts = value; }
            }

            static decimal checkDeposits;
            public decimal CheckDeposits
            {
                get { return checkDeposits; }
                set { checkDeposits = value; }
            }

            public static string _CheckOverNotes;
            public string CheckOverNotes
            {
                get { return _CheckOverNotes; }
                set { _CheckOverNotes = value; }
            }

            public static string _CashOverNotes;
            public string CashOverNotes
            {
                get { return _CashOverNotes; }
                set { _CashOverNotes = value; }
            }

            public static string _Weather;
            public string Weather
            {
                get { return _Weather; }
                set { _Weather = value; }
            }

            public static string _DaySummary;
            public string DaySummary
            {
                get { return _DaySummary; }
                set { _DaySummary = value; }
            }

            static string reportAddress1;
            public string ReportAddress1
            {
                get { return reportAddress1; }
                set { reportAddress1 = value; }
            }
            static string reportAddress2;

            public string ReportAddress2
            {
                get { return reportAddress2; }
                set { reportAddress2 = value; }
            }
            static string reportAddress3;

            public string ReportAddress3
            {
                get { return reportAddress3; }
                set { reportAddress3 = value; }
            }
            static string reportName;

            public string ReportName
            {
                get { return reportName; }
                set { reportName = value; }
            }
            static string reportRange;

            public string ReportRange
            {
                get { return reportRange; }
                set { reportRange = value; }
            }
            public static decimal grossSales;

            public decimal GrossSales
            {
                get { return grossSales; }
                set { grossSales = value; }
            }
            public static decimal netSales;

            public decimal NetSales
            {
                get { return netSales; }
                set { netSales = value; }
            }
            public static decimal totalComps;

            public decimal TotalComps
            {
                get { return totalComps; }
                set { totalComps = value; }
            }
            public static decimal totalVoids;

            public decimal TotalVoids
            {
                get { return totalVoids; }
                set { totalVoids = value; }
            }
            public static decimal totalPromos;
            public decimal TotalPromos
            {
                get { return totalPromos; }
                set { totalPromos = value; }
            }

            public static decimal _CheckAverage;
            public decimal CheckAverage
            {
                get { return _CheckAverage; }
                set { _CheckAverage = value; }
            }

            public static decimal _PerPersonAverage;
            public decimal PerPersonAverage
            {
                get { return _PerPersonAverage; }
                set { _PerPersonAverage = value; }
            }
            public static decimal compCount;
            public decimal CompCount
            {
                get { return compCount; }
                set { compCount = value; }
            }
            public static decimal voidCount;

            public decimal VoidCount
            {
                get { return voidCount; }
                set { voidCount = value; }
            }
            public static decimal promoCount;

            public decimal PromoCount
            {
                get { return promoCount; }
                set { promoCount = value; }
            }
            public static decimal _CheckCount;
            public decimal CheckCount
            {
                get { return _CheckCount; }
                set { _CheckCount = value; }
            }

            public static decimal _GuestCount;
            public decimal GuestCount
            {
                get { return _GuestCount; }
                set { _GuestCount = value; }
            }

            static string totalHours;
            public string TotalHours
            {
                get { return totalHours; }
                set { totalHours = value; }
            }
            static string regularHours;

            public string RegularHours
            {
                get { return regularHours; }
                set { regularHours = value; }
            }
            static string overtimeHours;

            public string OvertimeHours
            {
                get { return overtimeHours; }
                set { overtimeHours = value; }
            }
            static string totalPay;

            public string TotalPay
            {
                get { return totalPay; }
                set { totalPay = value; }
            }
            static string regularPay;

            public string RegularPay
            {
                get { return regularPay; }
                set { regularPay = value; }
            }
            static string overtimePay;

            public string OvertimePay
            {
                get { return overtimePay; }
                set { overtimePay = value; }
            }
            static string laborPercent;

            public string LaborPercent
            {
                get { return laborPercent; }
                set { laborPercent = value; }
            }
            static string averagePay;

            public string AveragePay
            {
                get { return averagePay; }
                set { averagePay = value; }
            }

            static decimal paymentsTotal;

            public decimal PaymentsTotal
            {
                get { return paymentsTotal; }
                set { paymentsTotal = value; }
            }
            static decimal gratuityTotal;

            public decimal GratuityTotal
            {
                get { return gratuityTotal; }
                set { gratuityTotal = value; }
            }
            static decimal taxTotal;

            public decimal TaxTotal
            {
                get { return taxTotal; }
                set { taxTotal = value; }
            }
            static decimal chargedAmountTotal;

            public decimal ChargedAmountTotal
            {
                get { return chargedAmountTotal; }
                set { chargedAmountTotal = value; }
            }

            static decimal inclusiveTaxes;

            public decimal InclusiveTaxes
            {
                get { return inclusiveTaxes; }
                set { inclusiveTaxes = value; }
            }
            static decimal exclusiveTaxes;

            public decimal ExclusiveTaxes
            {
                get { return exclusiveTaxes; }
                set { exclusiveTaxes = value; }
            }

            public static decimal _ExclusivelyTaxable;
            public decimal ExclusivelyTaxable
            {
                get { return _ExclusivelyTaxable; }
                set { _ExclusivelyTaxable = value; }
            }

            public static decimal _InclusivelyTaxable;
            public decimal InclusivelyTaxable
            {
                get { return _InclusivelyTaxable; }
                set { _InclusivelyTaxable = value; }
            }

            static decimal nonTaxableSales;

            public decimal NonTaxableSales
            {
                get { return nonTaxableSales; }
                set { nonTaxableSales = value; }
            }
            static decimal giftCardIncome;

            public decimal GiftCardIncome
            {
                get { return giftCardIncome; }
                set { giftCardIncome = value; }
            }
            static decimal giftCardComps;

            public decimal GiftCardComps
            {
                get { return giftCardComps; }
                set { giftCardComps = value; }
            }
            static decimal giftCardPromos;

            public decimal GiftCardPromos
            {
                get { return giftCardPromos; }
                set { giftCardPromos = value; }
            }
            static decimal cashDeposits;

            public decimal CashDeposits
            {
                get { return cashDeposits; }
                set { cashDeposits = value; }
            }

            static decimal overageShortage;
            public decimal OverageShortage
            {
                get { return overageShortage; }
                set { overageShortage = value; }
            }

            static decimal checkTotal;
            public decimal CheckTotal
            {
                get { return checkTotal; }
                set { checkTotal = value; }
            }

            static decimal cashOverage;
            public decimal CashOverage
            {
                get { return cashOverage; }
                set { cashOverage = value; }
            }

            static decimal visaSales;

            public decimal VisaTotal
            {
                get { return DisplayMasterSalesReport.visaSales; }
                set { DisplayMasterSalesReport.visaSales = value; }
            }
            static decimal masterCardSales;

            public decimal MasterCardTotal
            {
                get { return DisplayMasterSalesReport.masterCardSales; }
                set { DisplayMasterSalesReport.masterCardSales = value; }
            }
            static decimal discoverSales;

            public decimal DiscoverTotal
            {
                get { return DisplayMasterSalesReport.discoverSales; }
                set { DisplayMasterSalesReport.discoverSales = value; }
            }
            static decimal amexSales;

            public decimal AmexTotal
            {
                get { return DisplayMasterSalesReport.amexSales; }
                set { DisplayMasterSalesReport.amexSales = value; }
            }
            static decimal giftSales;

            public decimal GiftTotal
            {
                get { return DisplayMasterSalesReport.giftSales; }
                set { DisplayMasterSalesReport.giftSales = value; }
            }
            static decimal otherEdcSales;

            public decimal OtherEdcTotal
            {
                get { return DisplayMasterSalesReport.otherEdcSales; }
                set { DisplayMasterSalesReport.otherEdcSales = value; }
            }
            static decimal houseAccountSales;

            public decimal HouseAccountTotal
            {
                get { return DisplayMasterSalesReport.houseAccountSales; }
                set { DisplayMasterSalesReport.houseAccountSales = value; }
            }

            static decimal visaGrat;

            public decimal VisaGrat
            {
                get { return DisplayMasterSalesReport.visaGrat; }
                set { DisplayMasterSalesReport.visaGrat = value; }
            }
            static decimal masterGrat;

            public decimal MasterGrat
            {
                get { return DisplayMasterSalesReport.masterGrat; }
                set { DisplayMasterSalesReport.masterGrat = value; }
            }
            static decimal discoverGrat;

            public decimal DiscoverGrat
            {
                get { return DisplayMasterSalesReport.discoverGrat; }
                set { DisplayMasterSalesReport.discoverGrat = value; }
            }
            static decimal amexGrat;

            public decimal AmexGrat
            {
                get { return DisplayMasterSalesReport.amexGrat; }
                set { DisplayMasterSalesReport.amexGrat = value; }
            }
            static decimal giftGrat;

            public decimal GiftGrat
            {
                get { return DisplayMasterSalesReport.giftGrat; }
                set { DisplayMasterSalesReport.giftGrat = value; }
            }
            static decimal otherEdcGrat;

            public decimal OtherEdcGrat
            {
                get { return DisplayMasterSalesReport.otherEdcGrat; }
                set { DisplayMasterSalesReport.otherEdcGrat = value; }
            }

            static decimal cashTotal;
            public decimal CashTotal
            {
                get { return DisplayMasterSalesReport.cashTotal; }
                set { DisplayMasterSalesReport.cashTotal = value; }
            }

            /// <summary>
            /// For the detailed sales data
            /// </summary>
            string revenueType;
            public string RevenueType
            {
                get { return revenueType; }
                set { revenueType = value; }
            }
            decimal grossSalesForRevType;
            public decimal GrossSalesForRevType
            {
                get { return grossSalesForRevType; }
                set { grossSalesForRevType = value; }
            }

            decimal comps;
            public decimal Comps
            {
                get { return comps; }
                set { comps = value; }
            }
            decimal promos;
            public decimal Promos
            {
                get { return promos; }
                set { promos = value; }
            }
            decimal voids;
            public decimal Voids
            {
                get { return voids; }
                set { voids = value; }
            }
            decimal taxes;
            public decimal Taxes
            {
                get { return taxes; }
                set { taxes = value; }
            }
            decimal netSalesForRevenueType;
            public decimal NetSalesForRevenueType
            {
                get { return netSalesForRevenueType; }
                set { netSalesForRevenueType = value; }
            }
        }

        private static DateTime reportStartDate;
        public static DateTime ReportStartDate
        {
            get { return GetCalls.reportStartDate; }
            set { GetCalls.reportStartDate = value; }
        }
        private static DateTime reportEndDate;
        public static DateTime ReportEndDate
        {
            get { return GetCalls.reportEndDate; }
            set { GetCalls.reportEndDate = value; }
        }

        public static void SetReportDateTime(List<BUSINESS_DAY> bdays, DominicaEntities context)
        {
            if (bdays != null)
            {
                reportStartDate = bdays.Min(bd => bd.BusinessDayDateStamp);

                BUSINESS_DAY currentDay = BUSINESS_DAY.GetNow(context);
                bool hasOpenDate = bdays.Where(bd => bd.Id == currentDay.Id).Any();
                if (hasOpenDate)
                {
                    reportEndDate = DateTime.Now;
                }
                else
                {
                    reportEndDate = bdays.Where(bd => bd.CheckoutDateStamp != null).Max(bd => (DateTime)bd.CheckoutDateStamp);
                }
            }
        }

        private static List<SALE> GetSalesList(List<BUSINESS_DAY> bdays,
            out List<ORDER> outOrdersList,
            out List<DEPOSIT> outDepositsList,
            DominicaEntities logContext)
        {
            List<SALE> salesList = new List<SALE>();
            outOrdersList = new List<ORDER>();
            outDepositsList = new List<DEPOSIT>();

            SetReportDateTime(bdays, logContext);
            if (bdays != null && bdays.Count != 0)
            {
                foreach (BUSINESS_DAY bd in bdays)
                {
                    List<ORDER> orders = null;
                    if (logContext.ORDERS.Where(o => o.BusinessDayId == bd.Id).Any())
                    {
                        orders = logContext.ORDERS.Where(o => o.BusinessDayId == bd.Id).ToList();
                    }

                    if (orders != null)
                    {
                        foreach (ORDER order in orders)
                        {
                            if (order.SALES.Where(s => !s.IsSeeServer).Any())
                            {
                                salesList.AddRange(order.SALES.Where(s => !s.IsSeeServer));
                            }
                        }
                        outOrdersList.AddRange(orders);
                    }

                    if (bd.DEPOSIT.Any())
                    {
                        outDepositsList.AddRange(bd.DEPOSIT);
                    }
                }
                reportStartDate = bdays.Min(bd => bd.BusinessDayDateStamp);

                BUSINESS_DAY currentDay = BUSINESS_DAY.GetNow(logContext);
                bool hasOpenDate = bdays.Where(bd => bd.Id == currentDay.Id).Any();
                if (hasOpenDate)
                {
                    reportEndDate = DateTime.Now;
                }
                else
                {
                    if (bdays.Where(bd => bd.CheckoutDateStamp != null).Any())
                    {
                        reportEndDate = bdays.Where(bd => bd.CheckoutDateStamp != null).Max(bd => (DateTime)bd.CheckoutDateStamp);
                    }
                    else
                    {
                        reportEndDate = DateTime.Now;
                    }
                }
            }
            else
            {
                var q =
                    logContext.SALES.Where(s => !s.IsSeeServer && s.FirstOrderedDateTime >= reportStartDate && s.FirstOrderedDateTime <= ReportEndDate);
                if (q.Any())
                {
                    salesList = q.ToList();
                    outOrdersList.AddRange(from s in salesList select s.ORDER);
                }
            }
            return salesList;
        }

        private static List<TIMESLIP> GetTimePunchList(List<BUSINESS_DAY> bdays, DominicaEntities logContext)
        {
            SetReportDateTime(bdays, logContext);
            List<TIMESLIP> timePunchList = new List<TIMESLIP>();
            if (bdays != null)
            {
                foreach (BUSINESS_DAY bd in bdays)
                {
                    List<SHIFT> shifts = bd.SHIFTS.ToList();
                    foreach (SHIFT s in shifts)
                    {
                        if (s.TIMESLIP != null)
                        {
                            timePunchList.Add(s.TIMESLIP);
                        }
                        else
                        {
                            Logging.LogMessage("In reporting and the timeslip was null for shift ID = " + s.Id + ".");
                        }
                    }
                }
            }
            else
            {
                var q = logContext.TIMESLIPS
                    .Where(ts => ts.ClockedIn != null && ts.ClockedIn >= reportStartDate &&
                        ts.ClockedOut != null && ts.ClockedOut <= reportEndDate);
                if (q.Any())
                {
                    timePunchList = q.ToList();
                }

            }
            return timePunchList;
        }

        private static List<SALE> GetVoidsList(List<BUSINESS_DAY> bdays, DominicaEntities logContext)
        {
            SetReportDateTime(bdays, logContext);
            List<SALE> salesList = new List<SALE>();
            if (bdays != null)
            {
                foreach (BUSINESS_DAY bd in bdays)
                {
                    List<ORDER> ordersList = logContext.ORDERS.Where(o => o.BusinessDayId == bd.Id).ToList();

                    foreach (ORDER order in ordersList)
                    {
                        foreach (SALE sale in order.SALES.Where(s => s.DiscountManagerId != null && s.MenuPrice != 0 && s.WasVoided))
                        {
                            salesList.Add(sale);
                        }
                    }
                }
            }
            else
            {
                var q =
                    logContext.SALES.Where(s => s.DiscountManagerId != null
                        && s.MenuPrice != 0 && s.WasVoided && s.FirstOrderedDateTime >= reportStartDate
                        && s.FirstOrderedDateTime <= ReportEndDate);

                if (q.Any())
                {
                    salesList = q.ToList();
                }
            }
            return salesList;
        }

        private static List<SALE> GetCompsList(List<BUSINESS_DAY> bdays, DominicaEntities logContext)
        {
            SetReportDateTime(bdays, logContext);
            List<SALE> salesList = new List<SALE>();
            if (bdays != null)
            {
                foreach (BUSINESS_DAY bd in bdays)
                {
                    List<ORDER> ordersList = logContext.ORDERS.Where(o => o.BusinessDayId == bd.Id).ToList();

                    foreach (ORDER order in ordersList)
                    {
                        foreach (SALE sale in order.SALES.Where(s => s.WasCompedInEntire && s.MenuPrice != 0 && !s.IsSeeServer && !s.IsForcedModifier && !s.IsExceptionModifier))
                        {
                            salesList.Add(sale);
                        }
                    }
                }
            }
            else
            {
                var q =
                    logContext.SALES.Where(s => s.WasCompedInEntire &&
                        s.MenuPrice != 0 && !s.IsSeeServer && !s.IsForcedModifier && !s.IsExceptionModifier
                        && s.FirstOrderedDateTime >= reportStartDate
                        && s.FirstOrderedDateTime <= ReportEndDate);

                if (q.Any())
                {
                    salesList = q.ToList();
                }
            }
            return salesList;
        }

        private static List<SALE> GetDiscountsList(List<BUSINESS_DAY> bdays, DominicaEntities logContext)
        {
            SetReportDateTime(bdays, logContext);
            List<SALE> salesList = new List<SALE>();
            if (bdays != null)
            {
                foreach (BUSINESS_DAY bd in bdays)
                {
                    List<ORDER> ordersList = logContext.ORDERS.Where(o => o.BusinessDayId == bd.Id).ToList();

                    foreach (ORDER order in ordersList)
                    {
                        foreach (SALE sale in order.SALES.Where(s => s.DiscountManagerId != null && s.MenuPrice != 0 &&
                                    !s.WasCompedInEntire && !s.WasVoided))
                        {
                            salesList.Add(sale);
                        }
                    }
                }
            }
            else
            {
                var q =
                    logContext.SALES.Where(s => s.DiscountManagerId != null && s.MenuPrice != 0 &&
                                    !s.WasCompedInEntire && !s.WasVoided && s.FirstOrderedDateTime >= reportStartDate
                        && s.FirstOrderedDateTime <= ReportEndDate);

                if (q.Any())
                {
                    salesList = q.ToList();
                }
            }
            return salesList;
        }

        public class SalesNumbersView
        {
            private int countOrdered = 0;
            public int CountOrdered
            {
                get { return countOrdered; }
                set { countOrdered = value; }
            }

            private decimal discountedPrice;

            public decimal DiscountedPrice
            {
                get { return discountedPrice; }
                set { discountedPrice = value; }
            }

            private int wasComped;

            public int WasComped
            {
                get { return wasComped; }
                set { wasComped = value; }
            }
            private int wasVoided;

            public int WasVoided
            {
                get { return wasVoided; }
                set { wasVoided = value; }
            }
            private int wasPromod;

            public int WasPromod
            {
                get { return wasPromod; }
                set { wasPromod = value; }
            }
            private decimal compAmount;

            public decimal CompAmount
            {
                get { return compAmount; }
                set { compAmount = value; }
            }
            private decimal voidAmount;

            public decimal VoidAmount
            {
                get { return voidAmount; }
                set { voidAmount = value; }
            }
            private decimal promoAmount;

            public decimal PromoAmount
            {
                get { return promoAmount; }
                set { promoAmount = value; }
            }

            private decimal nonTaxableSales;
            public decimal NonTaxableSales
            {
                get { return nonTaxableSales; }
                set { nonTaxableSales = value; }
            }

            private long revTypeId;

            public long RevTypeId
            {
                get { return revTypeId; }
                set { revTypeId = value; }
            }

            long revCenterId;

            public long RevCenterId
            {
                get { return revCenterId; }
                set { revCenterId = value; }
            }

            private long dayPartId;
            public long DayPartId
            {
                get { return dayPartId; }
                set { dayPartId = value; }
            }

            private long userId;

            public long UserId
            {
                get { return userId; }
                set { userId = value; }
            }

            private long productGroup;
            public long ProductGroup
            {
                get { return productGroup; }
                set { productGroup = value; }
            }

            DayOfWeek dayOfWeek;

            public DayOfWeek DayOfWeek
            {
                get { return dayOfWeek; }
                set { dayOfWeek = value; }
            }

            private long productId;

            public long ProductId
            {
                get { return productId; }
                set { productId = value; }
            }

            private bool isForcedMod = false;

            public bool IsForcedMod
            {
                get { return isForcedMod; }
                set { isForcedMod = value; }
            }
            private bool isExceptionMod = false;

            public bool IsExceptionMod
            {
                get { return isExceptionMod; }
                set { isExceptionMod = value; }
            }

            private decimal grossPrice;
            public decimal GrossPrice
            {
                get { return grossPrice; }
                set { grossPrice = value; }
            }

            private decimal discountAmount;
            public decimal DiscountAmount
            {
                get { return discountAmount; }
                set { discountAmount = value; }
            }
        }

        public class TransactionNumbersView
        {
            decimal gratuityAmount;
            public decimal GratuityAmount
            {
                get { return gratuityAmount; }
                set { gratuityAmount = value; }
            }

            decimal totalSale;
            public decimal TotalSale
            {
                get { return totalSale; }
                set { totalSale = value; }
            }

            private int tenderType;
            public int TenderType
            {
                get { return tenderType; }
                set { tenderType = value; }
            }
        }

        private class TaxableTaxRate
        {
            decimal taxable = 0;
            public decimal Taxable
            {
                get { return taxable; }
                set { taxable = value; }
            }
            decimal tax = 0;
            public decimal Tax
            {
                get { return tax; }
                set { tax = value; }
            }

        }

        public static List<DisplayMasterSalesReport> GetMasterSalesReport(List<BUSINESS_DAY> bdays)
        {
            List<DisplayMasterSalesReport> list = new List<DisplayMasterSalesReport>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    if (bdays == null)
                    {
                        var q = logContext.BUSINESS_DAYS.Where(b => b.BusinessDayDateStamp >= reportStartDate && b.BusinessDayDateStamp <= reportEndDate);
                        if (q.Any())
                        {
                            bdays = q.ToList();
                        }
                        else
                        {
                            bdays = new List<BUSINESS_DAY>();
                        }
                    }
                    List<ORDER> ordersList;
                    List<DEPOSIT> depositsList;
                    List<SALE> salesList = GetSalesList(bdays, out ordersList, out depositsList, logContext);

                    SYSCONFIG sysCfg = SYSCONFIG.Get(logContext);
                    DisplayMasterSalesReport first = new DisplayMasterSalesReport();
                    first.InitDisplayMasterSalesReport();
                    first.ReportAddress1 = sysCfg.ReceiptLine1;
                    first.ReportAddress2 = sysCfg.ReceiptLine2;
                    first.ReportAddress3 = sysCfg.ReceiptLine3;
                    first.ReportName = sysCfg.ReceiptLine1 + " - " + "Master Sales Report";
                    first.ReportRange = reportStartDate.ToString("MM/dd/yy", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += reportStartDate.ToString(" h:mm tt", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += " to ";
                    first.ReportRange += reportEndDate.ToString("MM/dd/yy", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += reportEndDate.ToString(" h:mm tt", CultureInfo.CreateSpecificCulture("en-US"));

                    CommonCalls.GetTransactionalInfo(bdays, first);

                    first.PaidIns = CommonCalls.GetPaidIns(bdays);
                    first.PaidOuts = CommonCalls.GetPaidOuts(bdays);
                    first.BdayStart = CommonCalls.GetBusinessDayStarts(bdays);
                    first.NetSales = CommonCalls.GetNetSales(bdays);
                    first.ExclusiveTaxes = CommonCalls.GetExclusiveTaxInfo(bdays, out DisplayMasterSalesReport._ExclusivelyTaxable);
                    first.InclusiveTaxes = CommonCalls.GetInclusiveTaxInfo(bdays, out DisplayMasterSalesReport._InclusivelyTaxable);
                    first.NonTaxableSales = CommonCalls.GetNonTaxableSalesTotal(bdays);
                    first.AutoGratuity = CommonCalls.GetAutoGratuity(bdays);

                    CommonCalls.GetGuestInfo(bdays,
                        out DisplayMasterSalesReport._CheckCount,
                        out DisplayMasterSalesReport._CheckAverage,
                        out DisplayMasterSalesReport._GuestCount,
                        out DisplayMasterSalesReport._PerPersonAverage);

                    first.CashDeposits = CommonCalls.GetCashDepositInfo(bdays, out DisplayMasterSalesReport._CashOverNotes);
                    first.CheckDeposits = CommonCalls.GetCheckDepositInfo(bdays, out DisplayMasterSalesReport._CheckOverNotes);

                    CommonCalls.GetGeneralNotes(bdays, out DisplayMasterSalesReport._Weather, out DisplayMasterSalesReport._DaySummary);

                    first.OverageShortage = CommonCalls.GetOverage(first.CashDeposits,
                                                                   first.CheckDeposits,
                                                                   first.CashTotal,
                                                                   first.CheckTotal,
                                                                   first.BdayStart,
                                                                   first.PaidOuts,
                                                                   first.PaidIns,
                                                                   first.AutoGratuity,
                                                                   first.GratuityTotal);

                    ///For legacy database reasons.
                    if ((first.CashDeposits + first.CheckDeposits) == 0)
                    {
                        first.OverageShortage = 0;
                    }

                    List<DisplayPayrollLineType> listOfPayroll = GetEmployeePayroll(bdays);
                    if (listOfPayroll != null && listOfPayroll.Where(p => p.TotalPay != 0).Any())
                    {

                        decimal totalHours = decimal.Round(listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.Hours + p.OtHours),
                            2, MidpointRounding.AwayFromZero);
                        decimal totalPay = listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.TotalPay);

                        decimal regularHours = decimal.Round(listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.Hours),
                            2, MidpointRounding.AwayFromZero);
                        decimal regularPay = listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.Pay);

                        decimal overtimeHours = decimal.Round(listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.OtHours), 2, MidpointRounding.AwayFromZero);
                        decimal overtimePay = listOfPayroll.Where(p => p.TotalPay != 0).Sum(p => p.OtPay);


                        first.TotalHours = totalHours.ToString();
                        first.TotalPay = totalPay.ToString("c");

                        first.RegularHours = regularHours.ToString();
                        first.RegularPay = regularPay.ToString("c");

                        first.OvertimeHours = overtimeHours.ToString();
                        first.OvertimePay = overtimePay.ToString("c");

                        if (first.NetSales == 0)
                        {
                            first.LaborPercent = "100%";
                        }
                        else
                        {
                            first.LaborPercent = decimal.Round((100 * (totalPay / first.NetSales)), 2, MidpointRounding.AwayFromZero).ToString() + "%";

                        }
                        if (totalHours != 0)
                        {
                            first.AveragePay = (totalPay / totalHours).ToString("c");
                        }
                    }
                    else
                    {
                        first.TotalHours = "NO PAID HR";
                        first.TotalPay = 0.ToString("c");

                        first.RegularHours = "NO PAID HR";
                        first.RegularPay = 0.ToString("c");

                        first.OvertimeHours = "NO PAID HR";
                        first.OvertimePay = 0.ToString("c");
                        first.LaborPercent = "0%";
                        first.AveragePay = 0.ToString("c");
                    }

                    CommonCalls.GetSalesByRevTypeInfo(bdays, first, list);
                    list.Add(first);
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }
    

        public static List<DisplayVoids> GetDiscountsBy(List<BUSINESS_DAY> bdays, CommonCalls.REPORT_TYPE_ENUM type)
        {
            List<DisplayVoids> list = new List<DisplayVoids>();

            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    SetReportDateTime(bdays, logContext);

                    DisplayVoids first = new DisplayVoids();
                    SYSCONFIG sysCfg = SYSCONFIG.Get(logContext);
                    first.ReportAddress1 = sysCfg.ReceiptLine1;
                    first.ReportAddress2 = sysCfg.ReceiptLine2;
                    first.ReportAddress3 = sysCfg.ReceiptLine3;
                    first.ReportRange = reportStartDate.ToString("MM/dd/yy", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += reportStartDate.ToString(" h:mm tt", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += " to ";
                    first.ReportRange += reportEndDate.ToString("MM/dd/yy", CultureInfo.CreateSpecificCulture("en-US"));
                    first.ReportRange += reportEndDate.ToString(" h:mm tt", CultureInfo.CreateSpecificCulture("en-US"));

                    List<SALE> salesList = null;
                    if (type == CommonCalls.REPORT_TYPE_ENUM.VOIDS_BYTYPE)
                    {
                        first.ReportType = "Void Type";
                        first.SortFieldName = "Void";
                        first.SortFieldSentence = "Totals for all Void Types";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Voids by Void Type";
                        salesList = GetVoidsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.COMPS_BYTYPE)
                    {
                        first.ReportType = "Comp Type";
                        first.SortFieldName = "Comp";
                        first.SortFieldSentence = "Totals for all Comp Types";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Comps by Comp Type";
                        salesList = GetCompsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.PROMO_BYTYPE)
                    {
                        first.ReportType = "Promotion Type";
                        first.SortFieldName = "Promotion";
                        first.SortFieldSentence = "Totals for all Promotion Types";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Promotions by Promotion Type";
                        salesList = GetDiscountsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.VOIDS_BYMANAGER)
                    {
                        first.ReportType = "Manager";
                        first.SortFieldName = "Void";
                        first.SortFieldSentence = "Totals for all Managers";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Voids by Approving Manager";
                        salesList = GetVoidsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.COMPS_BYMANAGER)
                    {
                        first.ReportType = "Manager";
                        first.SortFieldName = "Comp";
                        first.SortFieldSentence = "Totals for all Managers";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Comps by Approving Manager";
                        salesList = GetCompsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.PROMO_BYMANAGER)
                    {
                        first.ReportType = "Manager";
                        first.SortFieldName = "Promotion";
                        first.SortFieldSentence = "Totals for all Managers";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Promotions by Approving Manager";
                        salesList = GetDiscountsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.VOIDS_BYEMPLOYEE)
                    {
                        first.ReportType = "Employee";
                        first.SortFieldName = "Void";
                        first.SortFieldSentence = "Totals for all Employees";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Voids by Requesting Employee";
                        salesList = GetVoidsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.COMPS_BYEMPLOYEE)
                    {
                        first.ReportType = "Employee";
                        first.SortFieldName = "Comp";
                        first.SortFieldSentence = "Totals for all Employees";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Comps by Requesting Employee";
                        salesList = GetCompsList(bdays, logContext);
                    }
                    else if (type == CommonCalls.REPORT_TYPE_ENUM.PROMO_BYEMPLOYEE)
                    {
                        first.ReportType = "Employee";
                        first.SortFieldName = "Promotion";
                        first.SortFieldSentence = "Totals for all Employees";
                        first.ReportName = sysCfg.ReceiptLine1 + " - " + "Promotions by Requesting Employee";
                        salesList = GetDiscountsList(bdays, logContext);
                    }

                    if (salesList != null && salesList.Count() > 0)
                    {
                        decimal grossVoids = salesList.Sum(s => s.CountOrdered * (s.MenuPrice));

                        if (type <= CommonCalls.REPORT_TYPE_ENUM.PROMO_BYTYPE)
                        {
                            List<Int64?> disctinctIds = salesList.Where(s => s.DiscountManagerId != null && s.DiscountId != null).Select(s => s.DiscountId).Distinct().ToList();
                            foreach (Int64 revId in disctinctIds)
                            {
                                foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                    .Where(s => s.DiscountId == revId)
                                    .GroupBy(g => g.ProductId)
                                    .OrderByDescending
                                    (g => g.Sum(s => s.CountOrdered * (s.MenuPrice))))
                                {
                                    DisplayVoids display = new DisplayVoids();
                                    display.Count = salesGroups.Sum(s => s.CountOrdered);
                                    display.ProductName = salesGroups.First().ProductName;
                                    display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.MenuPrice));

                                    display.VoidName = logContext.COMP_ACCOUNTS.Where(ca => ca.Id == revId).FirstOrDefault().Name;

                                    display.PercentOfVoids = display.TotalVoids / grossVoids;
                                    list.Add(display);
                                }
                            }
                        }
                        else if (type <= CommonCalls.REPORT_TYPE_ENUM.PROMO_BYMANAGER)
                        {
                            List<Int64?> disctinctIds = salesList.Where(s => s.DiscountManagerId != null && s.DiscountId != null).Select(s => s.DiscountManagerId).Distinct().ToList();
                            foreach (Int64 revId in disctinctIds)
                            {
                                foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                    .Where(s => s.DiscountManagerId == revId)
                                    .GroupBy(g => g.ProductId)
                                    .OrderByDescending
                                    (g => g.Sum(s => s.CountOrdered * (s.MenuPrice))))
                                {
                                    DisplayVoids display = new DisplayVoids();
                                    display.Count = salesGroups.Sum(s => s.CountOrdered);
                                    display.ProductName = salesGroups.First().ProductName;
                                    display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.MenuPrice));

                                    USER user = logContext.USERS.Where(ca => ca.Id == revId).FirstOrDefault();
                                    display.VoidName = user.FirstName + " " + user.LastName;

                                    display.PercentOfVoids = display.TotalVoids / grossVoids;
                                    list.Add(display);
                                }
                            }
                        }
                        else if (type <= CommonCalls.REPORT_TYPE_ENUM.PROMO_BYEMPLOYEE)
                        {
                            List<Int64> disctinctIds = salesList.Where(s => s.DiscountId != null).Select(s => s.UserId).Distinct().ToList();
                            foreach (Int64 revId in disctinctIds)
                            {
                                foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                    .Where(s => s.UserId == revId)
                                    .GroupBy(g => g.ProductId)
                                    .OrderByDescending
                                    (g => g.Sum(s => s.CountOrdered * (s.MenuPrice))))
                                {
                                    DisplayVoids display = new DisplayVoids();
                                    display.Count = salesGroups.Sum(s => s.CountOrdered);
                                    display.ProductName = salesGroups.First().ProductName;
                                    display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.MenuPrice));

                                    USER user = logContext.USERS.Where(ca => ca.Id == revId).FirstOrDefault();
                                    display.VoidName = user.FirstName + " " + user.LastName;

                                    display.PercentOfVoids = display.TotalVoids / grossVoids;
                                    list.Add(display);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static List<DisplayVoids> GetDiscountsByType(List<BUSINESS_DAY> bdays)
        {
            List<DisplayVoids> list = new List<DisplayVoids>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<SALE> salesList = GetDiscountsList(bdays, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossVoids = salesList.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));

                        List<Int64?> disctinctIds = salesList.Where(s => s.DiscountId != null).Select(s => s.DiscountId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.DiscountId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate))))
                            {
                                DisplayVoids display = new DisplayVoids();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));

                                display.VoidName =
                                    logContext.COMP_ACCOUNTS.Where(rc => rc.Id == revId).First().Name;

                                display.PercentOfVoids = display.TotalVoids / grossVoids;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static List<DisplayVoids> GetCompsByType(List<BUSINESS_DAY> bdays)
        {
            List<DisplayVoids> list = new List<DisplayVoids>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<SALE> salesList = GetCompsList(bdays, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossVoids = salesList.Sum(s => s.CountOrdered * (s.MenuPrice));

                        List<Int64?> disctinctIds = salesList.Where(s => s.DiscountManagerId != null).Select(s => s.DiscountId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.DiscountId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.MenuPrice))))
                            {
                                DisplayVoids display = new DisplayVoids();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.MenuPrice));

                                display.VoidName = logContext.COMP_ACCOUNTS.Where(ca => ca.Id == revId).FirstOrDefault().Name;

                                display.PercentOfVoids = display.TotalVoids / grossVoids;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static List<DisplayVoids> GetDiscountsByEmployee(List<BUSINESS_DAY> bdays)
        {
            List<DisplayVoids> list = new List<DisplayVoids>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<SALE> salesList = GetDiscountsList(bdays, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossVoids = salesList.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));

                        List<Int64> disctinctIds = salesList.Select(s => s.UserId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.UserId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate))))
                            {
                                DisplayVoids display = new DisplayVoids();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));

                                USER user = logContext.USERS.Where(rc => rc.Id == revId).First();
                                display.VoidName = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";

                                display.PercentOfVoids = display.TotalVoids / grossVoids;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static List<DisplayVoids> GetCompsByEmployee(List<BUSINESS_DAY> bdays)
        {
            List<DisplayVoids> list = new List<DisplayVoids>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<SALE> salesList = GetCompsList(bdays, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossVoids = salesList.Sum(s => s.CountOrdered * s.MenuPrice);

                        List<Int64> disctinctIds = salesList.Select(s => s.UserId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.UserId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.MenuPrice))))
                            {
                                DisplayVoids display = new DisplayVoids();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalVoids = salesGroups.Sum(s => s.CountOrdered * (s.MenuPrice));

                                USER user = logContext.USERS.Where(rc => rc.Id == revId).First();
                                display.VoidName = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";

                                display.PercentOfVoids = display.TotalVoids / grossVoids;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }


        public static List<DisplaySaleByRevType> GetSalesByEmployee(List<BUSINESS_DAY> bdays)
        {
            List<DisplaySaleByRevType> list = new List<DisplaySaleByRevType>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<ORDER> ordersList;
                    List<DEPOSIT> dontCare;
                    List<SALE> salesList = GetSalesList(bdays, out ordersList, out dontCare, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossSales = salesList.Sum(s => s.CountOrdered * s.ActualPrice);

                        List<Int64> disctinctIds = salesList.Select(s => s.UserId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.UserId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.ActualPrice - (s.ActualPrice * s.DiscountRate)))))
                            {
                                DisplaySaleByRevType display = new DisplaySaleByRevType();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalRevenue = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice - (s.ActualPrice * s.DiscountRate)));
                                display.TotalMenuPrice = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice));
                                display.TotalDiscount = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));
                                USER user = logContext.USERS.Where(rc => rc.Id == revId).First();
                                display.RevenueTypeName = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";


                                display.PercentOfSales = display.TotalMenuPrice / grossSales;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static List<DisplaySaleByRevType> GetSalesByRevCenter(List<BUSINESS_DAY> bdays)
        {
            List<DisplaySaleByRevType> list = new List<DisplaySaleByRevType>();
            try
            {
                using (DominicaEntities logContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    List<ORDER> ordersList;
                    List<DEPOSIT> dontCare;
                    List<SALE> salesList = GetSalesList(bdays, out ordersList, out dontCare, logContext);
                    if (salesList.Count() > 0)
                    {
                        decimal grossSales = salesList.Sum(s => s.CountOrdered * s.ActualPrice);

                        List<Int64> disctinctIds = salesList.Select(s => s.RevenueCenterId).Distinct().ToList();
                        foreach (Int64 revId in disctinctIds)
                        {
                            foreach (IGrouping<Int64, SALE> salesGroups in salesList
                                .Where(s => s.RevenueCenterId == revId)
                                .GroupBy(g => g.ProductId)
                                .OrderByDescending
                                (g => g.Sum(s => s.CountOrdered * (s.ActualPrice - (s.ActualPrice * s.DiscountRate)))))
                            {
                                DisplaySaleByRevType display = new DisplaySaleByRevType();
                                display.Count = salesGroups.Sum(s => s.CountOrdered);
                                display.ProductName = salesGroups.First().ProductName;
                                display.TotalRevenue = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice - (s.ActualPrice * s.DiscountRate)));
                                display.TotalMenuPrice = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice));
                                display.TotalDiscount = salesGroups.Sum(s => s.CountOrdered * (s.ActualPrice * s.DiscountRate));

                                display.RevenueTypeName =
                                    logContext.REVENUE_CENTERS.Where(rc => rc.Id == revId).First().Name;

                                display.PercentOfSales = display.TotalMenuPrice / grossSales;
                                list.Add(display);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return list;
        }

        public static string GetRevenueTypeById(Int64 id)
        {
            string type = null;
            using (DominicaEntities context = new DominicaEntities(DominicaEntities.GetEfConString()))
            {
                try
                {
                    type = context.REVENUE_TYPES.Where(t => t.Id == id).First().Name;
                }
                catch (Exception e)
                {
                    Logging.LogException(e);
                }
                return type;
            }
        }

        public static string GetEmployeeNameById(Int64 id)
        {
            string type = null;
            using (DominicaEntities context = new DominicaEntities(DominicaEntities.GetEfConString()))
            {
                try
                {
                    USER user = context.USERS.Where(t => t.Id == id).First();
                    type = user.FirstName + " " + user.LastName + " (" + user.UserName + ")";
                }
                catch (Exception e)
                {
                    Logging.LogException(e);
                }
                return type;
            }
        }

        public static string GetRevenueCenterById(Int64 id)
        {
            string type = null;
            using (DominicaEntities context = new DominicaEntities(DominicaEntities.GetEfConString()))
            {
                try
                {
                    type = context.REVENUE_CENTERS.Where(t => t.Id == id).First().Name;
                }
                catch (Exception e)
                {
                    Logging.LogException(e);
                }
                return type;
            }
        }

        public static string GetProductGroupById(Int64 id)
        {
            string type = null;
            using (DominicaEntities context = new DominicaEntities(DominicaEntities.GetEfConString()))
            {
                try
                {
                    type = context.PRODUCT_GROUPS.Where(t => t.Id == id).First().Name;
                }
                catch (Exception e)
                {
                    Logging.LogException(e);
                }
                return type;
            }
        }
    }
}
